﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Runtime.Serialization;


namespace LunchRoller
{
    [DataContract]
    public abstract class ViewModelBase : IDisposable ,INotifyPropertyChanged
    {




        

        private  LinkedList<Action >  _disposeActions =new LinkedList<Action>();
        /// <summary>
        /// 注册在销毁时需要做的操作
        /// </summary>
        /// <param name="newAction">新操作</param>
        protected void AddDisposeAction(Action newAction)
        {
            _disposeActions.AddLast(newAction);
        }

        /// <summary>
        /// 销毁，尝试运行所有注册的销毁操作
        /// </summary>
        public void Dispose()
        {
            var tryresult = _disposeActions.TryEach(a => a()).ToList();
        }

        
        /// <summary>
        /// 保存属性值的容器
        /// </summary>
        /// <typeparam name="TProperty"></typeparam>



        internal void RaisePropertyChanged(string message)
        {
            var pe = new PropertyChangedEventArgs(message);
            if (PropertyChanged!=null) PropertyChanged(this, pe);
        }

        public event PropertyChangedEventHandler PropertyChanged = (s,e) => { };
    }
    [DataContract]
    public class  PropertyContainer<TProperty>
    {
        /// <summary>
        /// 创建属性值容器
        /// </summary>
        /// <param name="info">属性名</param>
        public PropertyContainer(string info)
            : this
            (
                info,
                (v1, v2) => v1.Equals(v2),
                default(TProperty)
            )
        {

        }




        /// <summary>
        /// 创建属性值容器
        /// </summary>
        /// <param name="info">属性名</param>
        /// <param name="equalityComparer">判断两个值是否相等的比较器</param>
        public PropertyContainer(string info, Func<TProperty, TProperty, bool> equalityComparer)
            : this
            (
                info,
                equalityComparer,
                default(TProperty)
            )
        {



        }
        /// <summary>
        /// 创建属性值容器
        /// </summary>
        /// <param name="info">属性名</param>

        /// <param name="initValue">初始值</param>
        public PropertyContainer(string info, TProperty initValue)
            : this
            (
                info,
                (v1, v2) => v1.Equals(v2),
                initValue
            )
        {

        }


        /// <summary>
        /// 创建属性值容器
        /// </summary>
        /// <param name="info">属性名</param>
        /// <param name="equalityComparer">判断两个值是否相等的比较器</param>
        /// <param name="initValue">初始值</param>
        public PropertyContainer(string info, Func<TProperty, TProperty, bool> equalityComparer, TProperty initValue)
        {
            EqualityComparer = equalityComparer;
            PropertyName = info;
            _value = initValue;
        }

        /// <summary>
        /// 判断两个值是否相等的比较器
        /// </summary>
        public Func<TProperty, TProperty, bool> EqualityComparer { get; private set; }

        /// <summary>
        /// 属性名
        /// </summary>
        /// 
        [DataMember]
        public string PropertyName { get;  set; }

        /// <summary>
        /// 内布值
        /// </summary>
        TProperty _value;
        /// <summary>
        /// 值
        /// </summary>
        [DataMember]
        public TProperty Value
        {
            get { return _value; }
              set { _value = value; }
        }



        /// <summary>
        /// 保存值并且触发更改事件
        /// </summary>
        /// <param name="objectInstance">属性所在的ViewModel</param>
        /// <param name="value">属性值</param>
        public void SetValueAndTryNotify(ViewModelBase objectInstance, TProperty value)
        {
            InternalPropertyChange(objectInstance, value, ref _value, PropertyName);
        }

        /// <summary>
        /// 单纯保存值
        /// </summary>
        /// <param name="value">新值</param>
        public void SetValue(TProperty value)
        {
            _value = value;
        }
        /// <summary>
        /// 保存值并且触发更改事件
        /// </summary>
        
        /// <param name="objectInstance">属性所在的ViewModel</param>
        /// <param name="newValue">新值</param>
        /// <param name="currentValue">当前值</param>
        /// <param name="message">属性名</param>
        void InternalPropertyChange(ViewModelBase objectInstance, TProperty newValue, ref TProperty currentValue, string message)
        {

            var changing = !Object.Equals(newValue, currentValue);

            if (changing)
            {
                var oldvalue = currentValue;
                currentValue = newValue;
                objectInstance.RaisePropertyChanged(message);
                if (ValueChanged!=null) ValueChanged(this, new ValueChangedEventArgs<TProperty>(oldvalue, newValue));
            }
        }
        public event EventHandler<  ValueChangedEventArgs<TProperty>  > ValueChanged = (o, e) => { };

        
    }

    public class ValueChangedEventArgs<T> : EventArgs
    {

        public ValueChangedEventArgs(T oldValue, T newValue)
        {   
            NewValue=newValue;
            Oldvalue=oldValue;

        }
        public T NewValue { get; private set; }
        public T Oldvalue { get; private set; }

    }
}
